require 'rubygems'
require 'appscript'
require 'ftools'
require 'date'
require 'rake/gempackagetask'
require 'rake/rdoctask'

COMMON_FILES = FileList[
  'COPYING.txt',
  'README.txt',
]

COMMON_CPP_FILES = COMMON_FILES + FileList[
  'examples/*.cpp',
  'examples/media/*',
  'reference/cpp/**/*',
]

COMMON_RUBY_FILES = COMMON_FILES + FileList[
  'lib/gosu.rb',
  'lib/gosu/patches.rb',
  'lib/gosu/swig_patches.rb',
  'examples/*.rb',
  'examples/media/*',
  'reference/rdoc/**/*'
]

LINUX_FILES = COMMON_CPP_FILES + COMMON_RUBY_FILES + FileList[
  'Rakefile',
  'Gosu/**/*', 'GosuImpl/**/*',
  'linux/configure', 'linux/configure.ac', 'linux/Makefile.in'
]
LINUX_FILES.uniq!

GOSU_VERSION = ENV['GOSU_RELEASE_VERSION'] || '0.0.0'

task :version do
  throw "GOSU_RELEASE_VERSION must be set" if GOSU_VERSION == '0.0.0'

  components = GOSU_VERSION.split('.')
  
  File.open('Gosu/Version.hpp', 'w') do |file|
    file.puts '#ifndef GOSU_VERSION_HPP'
    file.puts '#define GOSU_VERSION_HPP'
    file.puts
    file.puts "#define GOSU_MAJOR_VERSION #{components[0]}"
    file.puts "#define GOSU_MINOR_VERSION #{components[1]}"
    file.puts "#define GOSU_POINT_VERSION #{components[2]}"
    file.puts "#define GOSU_VERSION \"#{GOSU_VERSION}\""
    file.puts
    file.puts '#endif'
  end
end

# Sets everything except 'platform' and 'files'.
def apply_gemspec_defaults s
  #### Basic information.
  s.name = 'gosu'
  s.version = GOSU_VERSION
  s.summary = '2D game development library.'
  s.description = <<EOS
  2D game development library.

  Gosu features easy to use and game-friendly interfaces to 2D graphics
  and text (accelerated by 3D hardware), sound samples and music as well as
  keyboard, mouse and gamepad/joystick input.

  Also includes demos for integration with RMagick, Chipmunk and Ruby-OpenGL.
EOS
  s.authors = ['Julian Raschke', 'Jan Luecker']
  s.date = Time.now.strftime '%Y-%m-%d'
  s.email = 'julian@raschke.de'
  s.homepage = 'http://code.google.com/p/gosu/'
  s.require_paths = ['lib']
  s.required_ruby_version = Gem::Requirement.new('>= 1.8.2')
  s.summary = '2D game development library.'
end


desc "Publish OmniFocus tasks in ToDo Wiki page"
task :todo do
  File.open "wiki/ToDo.wiki", "w" do |wiki_page|
    doc = Appscript.app("OmniFocus").default_document
    my_projects = doc.folders["Einzelprojekte"].projects.get
    gosu_projects = my_projects.select { |p| p.name.get =~ /^Gosu/ }
    
    wiki_page.puts "#summary List of upcoming To Do items, refreshed daily."
    wiki_page.puts "#labels Featured"
    wiki_page.puts
    wiki_page.puts "= To Do list ="
    wiki_page.puts
    wiki_page.puts "This list of tasks is exported automatically from my OmniFocus projects."
    wiki_page.puts "(Last update: #{Date.today})"
    wiki_page.puts
    
    $shown_tasks = []
    
    def wiki_page.list_tasks_in root, indent = 2
      root.tasks.get.each do |task|
        next if $shown_tasks.include? task or task.completed.get
        $shown_tasks << task
        puts "#{' ' * indent}* #{task.name.get}"
        list_tasks_in task, indent + 2 unless task.tasks.get.empty?
      end
    end  

    gosu_projects.each do |project|
      wiki_page.puts "== #{project.name.get} =="
      wiki_page.list_tasks_in project
    end
  end
  
  `svn update wiki` # Just for cleanliness' sake.
  
  diff = `svn diff wiki`
  if diff.count("\n") == 13 and diff =~ /Last update/ then
    # We have only changed the date, just revert.
    sh "svn revert wiki/ToDo.wiki"
  else
    sh "svn commit wiki -m 'To Do list refresh'"
  end
end

desc "Clean rdoc directory so all HTML will definitely be refreshed"
task :clean_rdoc do
  sh "rm -rf reference/rdoc/*"
end

Rake::RDocTask.new do |rd|  
  rd.main = "README.txt"
  rd.rdoc_dir = "reference/rdoc"
  rd.rdoc_files.include("reference/gosu.rb", "README.txt", "COPYING.txt", *Dir["reference/*.rdoc"])
  rd.title = "RubyGosu rdoc Reference"
  rd.template = "#{File.dirname(__FILE__)}/reference/rdoc-template/lib/allison"
end

desc "Build Ruby reference with rdoc"
task :ruby_docs => [:clean_rdoc, :rdoc] do
  # Make sure that there are no blatant syntax errors in gosu.rb
  sh "ruby reference/gosu.rb"
  # Copy the stylesheet over, wee!
  sh "cp reference/rdoc-style.css reference/rdoc/rdoc-style.css"
end

desc "Build C++ reference with doxygen"
task :cpp_docs do
  sh "cd reference && doxygen"
end

desc "Upload documentation to www.libgosu.org"
task :upload_docs => [:cpp_docs, :ruby_docs] do
  # Expect some errors here, for example copying the .svn subdirectories might break.
  sh "scp -C -r reference/cpp vu2040@eta.railshoster.de:~/htdocs/ || true"
  sh "scp -C -r reference/rdoc vu2040@eta.railshoster.de:~/htdocs/ || true"
end

namespace :mac do
  desc "Build Gosu.framework"
  task :cpp => [:version, :cpp_docs] do
    sh "cd mac && xcodebuild -project Gosu.xcodeproj -target Gosu -configuration Release"
  end

  desc "Build lib/gosu.for_1_8.bundle, lib/gosu.for_1_9.bundle and RubyGosu App.app"
  task :ruby => [:version, :ruby_docs] do
    sh "cd mac && xcodebuild -project Gosu.xcodeproj -target 'RubyGosu Core' -configuration 'Release'"
    sh "cd mac && xcodebuild -project Gosu.xcodeproj -target 'RubyGosu Core' -configuration 'Release with 1.9'"
    sh "cd mac && xcodebuild -project Gosu.xcodeproj -target 'RubyGosu App' -configuration 'Release with 1.9'"
    # TODO: MacRuby
  end

  MAC_ARCHIVE_FILENAME = "public/gosu-mac-#{GOSU_VERSION}.tar.gz"

  desc "Build the archive #{MAC_ARCHIVE_FILENAME}"
  task :archive => [:cpp, :version] do
    files = COMMON_CPP_FILES + FileList['Gosu.framework/**/*']
    sh "tar -czf #{MAC_ARCHIVE_FILENAME} #{files.map { |filename| "'#{filename}'" }.join(' ')}"
  end
  
  MAC_WRAPPER_FILENAME = "public/gosu-mac-wrapper-#{GOSU_VERSION}.tar.gz"
  
  desc "Publish RubyGosu App.app"
  task :app_wrapper => [:cpp, :ruby, :version] do
    files = FileList['RubyGosu App.app/**/*']
    sh "tar -czf #{MAC_WRAPPER_FILENAME} #{files.map { |filename| "'#{filename}'" }.join(' ')}"
  end

  desc "Releases the archive #{MAC_ARCHIVE_FILENAME} and #{MAC_WRAPPER_FILENAME} on GoogleCode"
  task :release => [:archive, :app_wrapper] do
    sh "./googlecode_upload.py --summary=\"Gosu #{GOSU_VERSION}, compiled for Mac OS X (C++)\"" +
       " --project=gosu --user=julianraschke --labels=\"Featured,Type-Archive,OpSys-OSX\" #{MAC_ARCHIVE_FILENAME}"
    sh "./googlecode_upload.py --summary=\"Self-contained template app, containing Gosu #{GOSU_VERSION} and Ruby 1.9\"" +
       " --project=gosu --user=julianraschke --labels=\"Featured,Type-Archive,OpSys-OSX\" #{MAC_WRAPPER_FILENAME}"
  end

  task :gem => [:ruby, :version]

  MAC_SPEC = Gem::Specification.new do |s|
    apply_gemspec_defaults s
    s.platform = 'universal-darwin'
    s.files = COMMON_RUBY_FILES + FileList['lib/gosu.*.bundle']
      # TODO: 'lib/hotgosu.rb', 'lib/hotgosu/**/*', 
  end
  Rake::GemPackageTask.new(MAC_SPEC) { |t| t.package_dir = 'public/mac_gem' }
  
  task :release_gem => :gem do
    sh "gem push public/mac_gem/gosu-#{GOSU_VERSION}-universal-darwin.gem"
  end
end

namespace :win do
  WINDOWS_CPP_ARCHIVE_FILENAME = "public/gosu-windows-cpp-#{GOSU_VERSION}.zip"
  
  desc "Build the archive #{WINDOWS_CPP_ARCHIVE_FILENAME}"
  task :cpp_archive => [:version] do
    files = COMMON_CPP_FILES + FileList['Gosu/*.hpp', 'lib/Gosu.lib', 'lib/GosuDebug.lib', 'lib/fmod.dll']
    sh "zip #{WINDOWS_CPP_ARCHIVE_FILENAME} #{files.map { |filename| "'#{filename}'" }.join(' ')}"
  end

  desc "Releases the archive #{WINDOWS_CPP_ARCHIVE_FILENAME} on GoogleCode"
  task :cpp_release => :cpp_archive do
    sh "./googlecode_upload.py --summary=\"Gosu #{GOSU_VERSION}, compiled for 32-bit Windows (C++)\"" +
       " --project=gosu --user=julianraschke --labels=\"Featured,Type-Archive,OpSys-Windows\" #{WINDOWS_CPP_ARCHIVE_FILENAME}"
  end

  WINDOWS_RUBY_ARCHIVE_FILENAME = "public/gosu-windows-ruby-#{GOSU_VERSION}.zip"

  desc "Build the archive #{WINDOWS_RUBY_ARCHIVE_FILENAME}"
  task :ruby_archive => [:version] do
    files = COMMON_RUBY_FILES + ['lib/gosu.for_1_8.so', 'lib/gosu.for_1_9.so', 'lib/fmod.dll']
    sh "zip #{WINDOWS_RUBY_ARCHIVE_FILENAME} #{files.map { |filename| "'#{filename}'" }.join(' ')}"
  end

  desc "Releases the archive #{WINDOWS_RUBY_ARCHIVE_FILENAME} on GoogleCode"
  task :ruby_release => :ruby_archive do
    sh "./googlecode_upload.py --summary=\"Gosu #{GOSU_VERSION}, compiled for 32-bit Windows (Ruby)\"" +
       " --project=gosu --user=julianraschke --labels=\"Featured,Type-Archive,OpSys-Windows\" #{WINDOWS_RUBY_ARCHIVE_FILENAME}"
  end
  
  desc "Release both #{WINDOWS_CPP_ARCHIVE_FILENAME} and #{WINDOWS_RUBY_ARCHIVE_FILENAME}"
  task :release => [:cpp_release, :ruby_release]

  task :gem => [:version]

  WINDOWS_SPEC = Gem::Specification.new do |s|
    apply_gemspec_defaults s
    s.platform = 'i386-mingw32'#'x86-mswin32-60' ...you can always force the gem platform
    s.files = COMMON_RUBY_FILES + ['lib/gosu.for_1_8.so', 'lib/gosu.for_1_9.so', 'lib/fmod.dll']
  end
  Rake::GemPackageTask.new(WINDOWS_SPEC) { |t| t.package_dir = 'public/windows_gem' }
  
  task :release_gem => :gem do
    sh "gem push public/windows_gem/gosu-#{GOSU_VERSION}-x86-mingw32.gem"
  end
end

namespace :linux do
  LINUX_ARCHIVE_FILENAME = "public/gosu-linux-#{GOSU_VERSION}.tar.gz"

  desc "Build the archive #{LINUX_ARCHIVE_FILENAME}"
  task :archive => [:cpp_docs, :version] do
    files = LINUX_FILES
    sh "cd .. && tar -czf gosu/#{LINUX_ARCHIVE_FILENAME} #{files.map { |filename| "'gosu/#{filename}'" }.join(' ')}"
  end

  desc "Releases the archive #{LINUX_ARCHIVE_FILENAME} on GoogleCode"
  task :release => :archive do
    sh "./googlecode_upload.py --summary=\"Gosu #{GOSU_VERSION} source package for Linux (primarily for C++)\"" +
       " --project=gosu --user=julianraschke --labels=\"Featured,Type-Archive,OpSys-All\" #{LINUX_ARCHIVE_FILENAME}"
  end
  
  task :gem => [:version]
  
  LINUX_SPEC = Gem::Specification.new do |s|
    apply_gemspec_defaults s
    s.platform = 'ruby'
    s.files = LINUX_FILES + [ 'linux/extconf.rb' ]
    s.extensions = [ 'linux/extconf.rb' ]
    s.require_path = 'lib'
    s.requirements = ['g++',
                      'pkg-config',
                      'libgl',
                      'X11 includes and libraries',
                      'pangoft2',
                      'SDL_mixer',
 
                      "(Packages for Debian/Ubuntu:\n" +
                      ' g++ pkg-config ruby-dev xorg-dev' +
                      ' libsdl-mixer1.2-dev libgl1-mesa-dev' +
                      ' libpango1.0-dev' +
                      "\n)"]
  end
  
  Rake::GemPackageTask.new(LINUX_SPEC) { |t| t.package_dir = 'public/linux_gem' }

  task :release_gem => :gem do
    sh "gem push public/linux_gem/gosu-#{GOSU_VERSION}.gem"
  end
end

GIT_PREFIX="PATH=/usr/local/git/bin:$PATH"

desc "Uses a parallel gosu.git repository and git-svn to push changes to github"
task :push_to_github do
  Dir.chdir '../gosu.git'
  fetch_output = `#{GIT_PREFIX} git svn fetch`
  puts fetch_output
  if not fetch_output.empty? then
    last_commit_id = fetch_output.reverse[/ [a-f0-9]{40} /].reverse
    sh "#{GIT_PREFIX} git rebase #{last_commit_id}"
    sh "#{GIT_PREFIX} git push origin master"
  end
end

# TODO? Gem upload to RubyForge: http://nubyonrails.com/articles/tutorial-publishing-rubygems-with-hoe
